package samples.activiti;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormData;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.impl.form.DateFormType;
import org.activiti.engine.impl.form.LongFormType;
import org.activiti.engine.impl.form.StringFormType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * 流程引擎入门DEMO, 此DEMO实现流程如下:
 * 1. 输入姓名和名称
 * 2. 如果年龄大于等于18岁，则欢迎用户登录此站（什么站就不说了），祝其玩得愉快；
 * 3. 如果年龄小于18岁，告诉其年龄太小，劝其离开。
 *
 * @author zilaiye
 * @date 2017/10/27
 */
public class WebsiteLogonProcessEngine {
    public static final Logger logger = LoggerFactory.getLogger(WebsiteLogonProcessEngine.class);

    public static void main(String[] args) throws ParseException {
        // 1. 配置 Activiti 流程引擎
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
            .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000")
            .setJdbcUsername("sa")
            .setJdbcPassword("")
            .setJdbcDriver("org.h2.Driver")
//            .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
//            .setJdbcUrl("jdbc:mysql://mysql.master.dev.7mxing.com:3306/wychuan?useSSL=false")
//            .setJdbcUsername("dbadmin")
//            .setJdbcPassword("2016admin*JYW")
//            .setJdbcDriver("com.mysql.jdbc.Driver")
//            .setProcessEngineName("test")
            .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 2. 获取 Activiti 流程引擎对象
        ProcessEngine processEngine = cfg.buildProcessEngine();
        String pName = processEngine.getName();
        String ver = ProcessEngine.VERSION;
        System.out.println("获取流程引擎对象完成: ProcessEngine Name: [ " + pName + " ] Version: [ " + ver + " ]");

        // 3. 加载流程定义
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment().addClasspathResource("logon-bpmn20.xml").deploy();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
        System.out.println("发现流程定义, 名称:[" + processDefinition.getName() + "] Id:[" + processDefinition.getId() + "]");
////
        // 4. 运营流程实例
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 启动一个流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("yellow-site-logon");
        System.out.println("登录判断流程开始,流程实例ID:[" + processInstance.getProcessDefinitionId() + "] key:[" + processInstance.getProcessDefinitionKey() + "]");

        // 流程中的任务
        TaskService taskService = processEngine.getTaskService();
        FormService formService = processEngine.getFormService();
        HistoryService historyService = processEngine.getHistoryService();

        Scanner scanner = new Scanner(System.in);
        while (processInstance != null && !processInstance.isEnded()) {
            // 获取流程的所有运行任务
            List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
            System.out.println("此流程共有任务数量: [ " + tasks.size() + "]");
            // 循环任务执行之
            for (int i = 0; i < tasks.size(); i++) {
                Task task = tasks.get(i);
                System.out.println("开始执行流程任务: [" + task.getName() + "]");
                Map<String, Object> variables = new HashMap<String, Object>();
                FormData formData = formService.getTaskFormData(task.getId());
                for (FormProperty formProperty : formData.getFormProperties()) {
                    if (StringFormType.class.isInstance(formProperty.getType())) {
                        System.out.println(formProperty.getName() + "?");
                        String value = scanner.nextLine();
                        variables.put(formProperty.getId(), value);
                    } else if (LongFormType.class.isInstance(formProperty.getType())) {
                        System.out.println(formProperty.getName() + "? (Must be a whole number)");
                        Long value = Long.valueOf(scanner.nextLine());
                        variables.put(formProperty.getId(), value);
                    } else if (DateFormType.class.isInstance(formProperty.getType())) {
                        System.out.println(formProperty.getName() + "? (Must be a date m/d/yy)");
                        DateFormat dateFormat = new SimpleDateFormat("m/d/yy");
                        Date value = dateFormat.parse(scanner.nextLine());
                        variables.put(formProperty.getId(), value);
                    } else {
                        System.out.println("<form type not supported>");
                    }
                }
                taskService.complete(task.getId(), variables);

                System.out.println("流程处理完成, 现在开始回放处理过程:");
                HistoricActivityInstance endActivity = null;
                List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstance.getId()).finished()
                    .orderByHistoricActivityInstanceEndTime().asc()
                    .list();
                for (HistoricActivityInstance activity : activities) {
                    if (activity.getActivityType() == "startEvent") {
                        System.out.println("流程处理开始, 实例名称:[" + processDefinition.getName() + "] Key:[" + processInstance.getProcessDefinitionKey() + "] 开始处理时间: [" + activity.getStartTime() + "]");
                    }
                    if (activity.getActivityType() == "endEvent") {
                        // Handle edge case where end step happens so fast that the end step
                        // and previous step(s) are sorted the same. So, cache the end step
                        //and display it last to represent the logical sequence.
                        endActivity = activity;
                    } else {
                        System.out.println("-- " + activity.getActivityName()
                            + " [" + activity.getActivityId() + "] "
                            + activity.getDurationInMillis() + " ms");
                    }
                }
                if (endActivity != null) {
                    System.out.println("-- " + endActivity.getActivityName()
                        + " [" + endActivity.getActivityId() + "] "
                        + endActivity.getDurationInMillis() + " ms");
                    System.out.println("流程处理完成 " + processDefinition.getName() + " ["
                        + processInstance.getProcessDefinitionKey() + "] "
                        + endActivity.getEndTime());
                }
            }
            // Re-query the process instance, making sure the latest state is available
            processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
        }
        scanner.close();
    }
}
